package scatter.pay.rest.third;

import cn.hutool.core.util.RandomUtil;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import scatter.common.rest.exception.BusinessException;
import scatter.common.rest.tools.InterfaceTool;
import scatter.order.pojo.constant.OrderConstants;
import scatter.order.rest.service.IOrderService;
import scatter.pay.pojo.form.WxPaySignForm;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *
 * </p>
 *
 * @author yangwei
 * @since 2021-07-03 18:40
 */
@Component
public class WxPaySignHelper implements InterfaceTool {

	@Autowired
	private IOrderService iOrderService;

	@Autowired
	private WxPayService wxPayService;

	public  Object paySign(WxPaySignForm form){


		String prepayId = form.getPrepayId();
		if (isStrEmpty(prepayId)) {
			// TODO: 2021/7/3 如果为空，尝试用订单号查询
		}


		if (StringUtils.isBlank(prepayId)) {
			throw new BusinessException("无法获取prepay id");
		}
		wxPayService.switchover(form.getAppCode());
		WxPayConfig config = wxPayService.getConfig();


		if (isEqual(form.getPayChannelDictValue(), OrderConstants.OrderPayChannelDictItem.wx_app.itemValue())) {
			return wxPayAppOrderResult(config, form.getSignType(), form.getPrepayId());
		}else
		if (isEqual(form.getPayChannelDictValue(), OrderConstants.OrderPayChannelDictItem.wx_jsapi.itemValue())) {
			return wxPayMpOrderResult(config, form.getSignType(), form.getPrepayId());
		}

		throw new RuntimeException("暂不支付该类型 payChannelDictValue=["+form.getPayChannelDictValue()+"]");

	}

	/**
	 * 微信app调起支付签名
	 * @param config
	 * @param signType
	 * @param prepayId
	 * @return
	 */
	private WxPayAppOrderResult wxPayAppOrderResult(WxPayConfig config,String signType,String prepayId){
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		String nonceStr = RandomUtil.randomString(32);
		if (signType == null) {
			signType = WxPayConstants.SignType.MD5;
		}
		// APP支付绑定的是微信开放平台上的账号，APPID为开放平台上绑定APP后发放的参数
		String appId = config.getAppId();
		if (StringUtils.isNotEmpty(config.getSubAppId())) {
			appId = config.getSubAppId();
		}

		Map<String, String> configMap = new HashMap<>(8);
		// 此map用于参与调起sdk支付的二次签名,格式全小写，timestamp只能是10位,格式固定，切勿修改
		String partnerId = config.getMchId();
		if (StringUtils.isNotEmpty(config.getSubMchId())) {
			partnerId = config.getSubMchId();
		}

		configMap.put("prepayid", prepayId);
		configMap.put("partnerid", partnerId);
		String packageValue = "Sign=WXPay";
		configMap.put("package", packageValue);
		configMap.put("timestamp", timestamp);
		configMap.put("noncestr", nonceStr);
		configMap.put("appid", appId);

		final WxPayAppOrderResult result = WxPayAppOrderResult.builder()
				.sign(SignUtils.createSign(configMap, signType, config.getMchKey(), null))
				.prepayId(prepayId)
				.partnerId(partnerId)
				.appId(appId)
				.packageValue(packageValue)
				.timeStamp(timestamp)
				.nonceStr(nonceStr)
				.build();
		return  result;
	}

	/**
	 * 公众号jsapi调起支付签名
	 * @param config
	 * @param signType
	 * @param prepayId
	 * @return
	 */
	private WxPayMpOrderResult wxPayMpOrderResult(WxPayConfig config,String signType,String prepayId){
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		String nonceStr = RandomUtil.randomString(32);

		if (signType == null) {
			signType = WxPayConstants.SignType.MD5;
		}

		String appid = config.getAppId();
		if (StringUtils.isNotEmpty(config.getSubAppId())) {
			appid = config.getSubAppId();
		}
		WxPayMpOrderResult payResult = WxPayMpOrderResult.builder()
				.appId(appid)
				.timeStamp(timestamp)
				.nonceStr(nonceStr)
				.packageValue("prepay_id=" + prepayId)
				.signType(signType)
				.build();
		payResult.setPaySign(SignUtils.createSign(payResult, signType, config.getMchKey(), null));

		return payResult;
	}

}
